﻿using System;
using System.ServiceModel;
using UI.Process.ServiceReference;

namespace UI.Process
{
    public delegate void GetTokenAsyncCompletedEventHandler(object sender, string token);

    public class TokenProcess
    {
        private string ClientTag { get; set; }
        private readonly ServiceClient _client;
        public event GetTokenAsyncCompletedEventHandler GetTokenAsyncCompleted;

        public TokenProcess(string tag)
        {
            ClientTag = tag;
            _client = new ServiceClient();
        }

        #region Sync

        public string GetToken()
        {
            string result = null;
            TokenRequest request = MakeRequest();
            try
            {
                var getTokenResponseSync = _client.GetToken(request);
                if (getTokenResponseSync.ResponseHeader.Status == OperationStatus.Success)
                {
                    result = getTokenResponseSync.SecurityToken;
                }
            }
            catch (TimeoutException ex)
            {
                throw new Exception("Timeout", ex);
            }
            catch (FaultException<ServiceFault> ex)
            {
                throw new Exception("ServiceFault", ex);
            }
            return result;
        }

        #endregion

        #region Async Server

        public void GetTokenServerAsync()
        {
            TokenRequest request = MakeRequest();
            _client.BeginGetToken(request, OnEndGetToken, null);
        }

        private void OnEndGetToken(IAsyncResult ar)
        {
            var response = _client.EndGetToken(ar);
            OnGetTokenAsyncCompleted(response.ResponseHeader.Status == OperationStatus.Success
                                               ? response.SecurityToken
                                               : null);
        }

        #endregion

        #region Async Client

        public void GetTokenClientAsync()
        {
            TokenRequest request = MakeRequest();
            _client.GetTokenCompleted += GetTokenCallback;
            _client.GetTokenAsync(request);
        }

        private void GetTokenCallback(object sender, GetTokenCompletedEventArgs e)
        {
            var response = e.Result;
            if (response.ResponseHeader.Status == OperationStatus.Success)
                OnGetTokenAsyncCompleted(response.ResponseHeader.Status == OperationStatus.Success
                                             ? response.SecurityToken
                                             : null);
        }

        #endregion

        private void OnGetTokenAsyncCompleted(string token)
        {
            if (GetTokenAsyncCompleted != null)
            {
                GetTokenAsyncCompleted(this, token);
            }
        }

        private TokenRequest MakeRequest()
        {
            return new TokenRequest
                       {
                           RequestHeader = new RequestHeader
                                               {
                                                   ClientTag = ClientTag,
                                                   RequestId = Guid.NewGuid().ToString()
                                               }
                       };
        }
    }
}
